DUT-Info/S3/M3105 (CPOA)

Jean-Michel Bruel
jbruel@gmail.com
version 1.0, 2014-11-18 - First draft

Suivre ces slides sur Internet…​

http://bit.ly/jmb_cpoa
http://iut-blagnac.github.io/cpoa/

Introduction

Ce cours porte sur la Conception et Programmation Objet Avancée.

Concepts, bonnes pratiques et patrons

Vous avez appris (cf. M2103 et M2104) un certain nombre de concepts objets :

  • Abstraction
  • Encapsulation
  • Polymorphisme
  • Héritage

Concepts, bonnes pratiques et patrons (suite)

Vous avez/allez ensuite appris des bonnes pratiques :

  • Identifier les aspects qui varient et les séparer des aspects constants
  • Programmer une interface, non une implémentation
  • Préférer la composition à l’héritage
  • Les classes doivent être ouvertes à l’extension, mais fermées à la modification
  • Dépendez d’abstractions. Ne dépendez pas de classes concrètes (inversion des dépendances)
  • Ne parlez pas aux inconnus

Concepts, bonnes pratiques et patrons (suite)

L’étape suivante consiste à apprendre les bonnes solutions de conception, ce qu’on appelle les patrons de conception (ou design patterns en anglais).

Organisation

Note

Rappel du rythme : 1 cours, 1 TD et 2 TPs par semaine. Pendant 8 semaines.

  • La première semaine est consacré au principe des patrons de conception, en partant d’un exemple (cours en fin de semaine).
  • Les 5 suivantes sont consacrées à l’étude de certains patrons classiques. Mise en pratique sur des exercices en TP.

    Note

    Les TPs sont décalés d’une semaine (conception et étude d’un ou plusieurs patrons semaine N et mise en oeuvre en TP semaine N+1).

  • Les 3 suivantes, les étudiants en mode projet pour faire du refactoring d’applications réelles (conception aidée en TD sur les modèles UML™, mise en oeuvre en TP).

Organisation (suite)

Voici une proposition de déroulement des semaines :

Semaine 1

SuperCanard, le grand classique, [Stratégie]

Semaine 2

L’exemple de Meyer : menus en objet

Semaine 3

Premiers patrons

Semaine 4

Patrons Fabrique, Proxy, Etat

Semaine 5

Patrons Décorateur, Façade, Visiteur

Semaine 6
  • MVC avec l’exemple JTable de Java
  • Patrons Chaîne de responsabilité (juste en cours)
Semaines 7 et 8
  • Quelques idées de projet final :

    • Refactorer un code généré par Umple.
    • Refactorer le code de MPA (mais pas le leur, celui d’un autre groupe)

Evaluation et notation

Comme prévu par le planning des contrôles, les étudiants auront :

  • une note de projet (TPs + projet final) ⇒ coef. 1
  • une note d’examen final (semaine 5) ⇒ coef. 2

Importance du typage

Différents types de typage

Le fait d’attribuer un type (une classe) à une variable (un objet) peut se faire de plusieurs façons :

  • statique
  • dynamique
  • duck typing

Typage statique

On parle de typage statique quand la majorité des vérifications de type sont effectuées au moment de la compilation.

Exemple de typage statique
int i = 0;  // cette déclaration indique explicitement que
            // la variable i est de type entier

Typage dynamique

Le typage dynamique consiste à laisser l’ordinateur réaliser l’opération de typage à la volée, lors de l’exécution du code.

Typage dynamique (exemple)

Exemple de typage dynamique
class A{
	int x;
}

class B extends A{
	int y;
}

...
A v1 = new B();
B v2 = (B) v1;

Duck typing

Style de typage dynamique où la sémantique d’un objet (c’est-à-dire son type) est déterminée par l’ensemble de ses méthodes et de ses attributs, et non par un type défini et nommé explicitement par le programmeur.

Note

L’origine de cette expression est liée à cette citation :

Si je vois un animal qui vole comme un canard, cancane comme un canard, et nage comme un canard, alors j’appelle cet oiseau un canard.

James Whitcomb Riley

Duck typing (exemple)

Exemple de duck typing
function calcule(a, b, c) => return (a+b)*c

a = calcule (1, 2, 3)
b = calcule ('pommes ', 'et oranges, ', 3)

print to_string a
print to_string b

Ce qui donne :

9
"pommes et oranges, pommes et oranges, pommes et oranges, "

Importance de la visibilité

Dès que l’on commence à avoir une application conséquente, l’organisation en package devient obligatoire. Revenons donc sur les questions de visibilité des propriétés et méthodes, qui seront importants dans la plupart des aspects de ce module.

Si un champ d’une classe A :

  • est private, il est accessible uniquement depuis sa propre classe ;
  • a la visibilité package (par défaut), il est accessible de partout dans le paquetage de A mais de nulle part ailleurs ;
  • est protected, il est accessible de partout dans le paquetage de A et, si A est publique, grosso modo dans les classes héritant de A dans d’autres paquetages ;
  • est public, il est accessible de partout dans le paquetage de A et, si A est publique, de partout ailleurs.
Note Ci-dessus, les niveaux de visibilité sont rangés par visibilité croissante.

Importance de la visibilité (exemple)

package UN;
public class A {
  protected String attrprotected;
  String attrfriend; // friend
}

Si on définit une deuxième classe dans le même package :

package UN;
class B {
  ...
{
    A a = new A ();
    a.attrprotected// OK : même si bizarre
    a.attrfriend  // OK : visible package
}
}

package UN;
class C extends A {
...
{
    this.attrprotected// OK : normal
    this.attrfriend // OK : visible package
}
}

Importance de la visibilité (suite de l’exemple)

package DEUX;
class B {
  ...
{
    A a = new A ();
    a.attrprotected// NON OK : normal
    a.attrfriend  // NON OK : normal, proche de "private"
}
}

class C extends A {
  ...
{
    this.attrprotected// OK : normal car protected et héritage
    this.attrfriend // NON OK : normal, proche de "private"
}
}

Visibilité et UML

Note Il n’y a pas de visibilité par défaut en UML™.

Design patterns

Introduction : importance des patrons

phdComics
–––––––––––––––––– Science is what we understand well enough to explain to a computer. Art is everything else we do. ––––––––––––––––––
Donald Knuth

Point sur le TD de la semaine passée

Principes de conception

Note
Principe de conception

Identifiez les apsects de votre code qui varient et séparez-les de ceux qui demeurent constant.

Principes de conception (suite)

Note
Principe de conception

Programmer une interface, non une implémentation.

Principes de conception (suite)

Note
Principe de conception

Préférez la composition à l’héritage.

Premier patron

Note
Design pattern : Stratégie (Strategy)

Stratégie définit une famille d’algorithmes, encapsule chacun d’eux et les rend interchangeables. Il permet à l’algorithme de varier indépendamment des clients qui l’utilisent.

strategy

Premier exemple d’utilisation de patron

Autre exemple concret

Note Cet exemple est tiré de ce cours.

Le problème

Vous avez une classe FileWriter qui a pour rôle d’écrire dans un fichier ainsi qu’une classe DBWriter. Dans un premier temps, ces classes ne contiennent qu’une méthode write() qui n’écrira que le texte passé en paramètre.

Au fil du temps, vous vous rendez compte que c’est dommage qu’elles ne fassent que ça et vous aimeriez bien qu’elles puissent écrire en différents formats (HTML, XML, etc.) : les classes doivent donc formater puis écrire.

Autre exemple concret (suite)

La solution

Autre exemple concret (suite)

Note
L’interface en PHP (code source ici)
<?php
interface Formater
{
  public function format($text);
}
?>

Autre exemple concret (suite)

Note
La classe abstraite Writer (code source ici)
<?php
abstract class Writer
{
  // Attribut contenant l'instance du formateur que l'on veut utiliser.
  protected $formater;

  abstract public function write($text);

  // Nous voulons une instance d'une classe implémentant Formater en paramètre.
  public function __construct(Formater $formater)
  {
    $this->formater = $formater;
  }
}
?>

Autre exemple concret (suite)

Note
La classe FileWriter (code source ici)
<?php
class FileWriter extends Writer
{
  // Attribut stockant le chemin du fichier.
  protected $file;

  public function __construct(Formater $formater, $file)
  {
    parent::__construct($formater);
    $this->file = $file;
  }

  public function write($text)
  {
    $f = fopen($this->file, 'w');
    fwrite($f, $this->formater->format($text));
    fclose($f);
  }
}
?>

Autre exemple concret (suite)

Note
La classe DBWriter (code source ici)
<?php
class DBWriter extends Writer
{
  protected $db;

  public function __construct(Formater $formater, PDO $db)
  {
    parent::__construct($formater);
    $this->db = $db;
  }

  public function write ($text)
  {
    $q = $this->db->prepare('INSERT INTO lorem_ipsum SET text = :text');
    $q->bindValue(':text', $this->formater->format($text));
    $q->execute();
  }
}
?>

Autre exemple concret (suite)

Enfin, nous avons nos trois formateurs. L’un ne fait rien de particulier (TextFormater), et les deux autres formatent le texte en deux langages différents (HTMLFormater et XMLFormater).

Autre exemple concret (suite)

Note
La classe TextFormater (code source ici)
<?php
class TextFormater implements Formater
{
  public function format($text)
  {
    return 'Date : ' . time() . "\n" . 'Texte : ' . $text;
  }
}
?>

Autre exemple concret (suite)

Note
La classe HTMLFormater (code source ici)
<?php
class HTMLFormater implements Formater
{
  public function format($text)
  {
    return '<p>Date : ' . time() . '<br />' ."\n". 'Texte : ' . $text . '</p>';
  }
}
?>

Autre exemple concret (suite)

Note
La classe XMLFormater (code source ici)
<?php
class XMLFormater implements Formater
{
  public function format($text)
  {
    return '<?xml version="1.0" encoding="ISO-8859-1"?>' ."\n".
           '<message>' ."\n".
           "\t". '<date>' . time() . '</date>' ."\n".
           "\t". '<texte>' . $text . '</texte>' ."\n".
           '</message>';
  }
}
?>

D’autres exemples

  • La fonction standard sort() de python

    >>> sorted("This is a test string from Andrew".split(), key=str.lower)
    ['a', 'Andrew', 'from', 'is', 'string', 'test', 'This']

  • Stratégie de cryptage en fonction de la taille d’un fichier

    File file = getFile();
     Cipher c = CipherFactory.getCipher( file.size() );
     c.performAction();
    
    // implementations:
    interface  Cipher  {
         public void performAction();
    }
    class InMemoryCipherStrategy implements Cipher {
             public void performAction() {
                 // load in byte[] ....
             }
    }
    class SwaptToDiskCipher implements Cipher {
             public void performAction() {
                 // swapt partial results to file.
             }
    }

Tip Plus de détails ici

(non) Réutilisation

Warning Les patrons ne sont pas réutilisables!

Il faut implémeter la solution qu’il représente à chaque fois.

Réutilisation (exception)

Exception : certains font l’objet d’une librairie.

Par exemple le patron Singleton existe dans la bibliothèque standard du langage en Ruby. C’est un mixin qu’il suffit d’inclure dans la classe qui doit être un singleton.

class Klass
   include Singleton
   # ...
end

a,b  = Klass.instance, Klass.instance

a == b
# => true

Klass.new
# => NoMethodError - new is private ...

Un peu d’histoire

1977

Alexander : patterns pour les architectures (les vraies)

1987

Beck et Cunningham : patterns pour des interfaces utilisateurs

1988

Meyer : livre sur l’orienté objet (langage Eiffel), devenu la bible pour beaucoup de programmeurs (cf. [Meyer88])

1990-1995

Gamma, Helm, Johnson et Vlissides : LE livre de référence (cf. [GoF]) NOTE: Les patterns de ce livre sont connus comme les Gof pour « Gang of Four ».

2003

Martin : principes SOLID (cf. [Martin03])

2004

Craig Larman décrit des modèles de conception : les Patterns GRASP (cf. [Larman05])

Exemples de bons principes

SOLID:

  • Single Responsibility Principle
  • Open-Closed Principle
  • Liskov Substitution Principle
  • Interface Segregation Principle
  • Dependency Inversion Principle

Single Responsibility Principle

solid s
Responsabilité => Sujet à changement

Open-Closed Principle

solid o
Ouvert à l'extension mais fermé à la modification

Open-Closed Principle (suite)

Tip Une fois écrite et testée, une classe ne devrait être modifiée que pour être corrigée! Toute modification devrait être possible par extension.

Liskov Substitution Principle

solid l
Une classe doit pouvoir être remplacée par une instance d'un de ses
sous-types, sans modifier la cohérence du programme

LSP : un exemple

Un carré est un rectangle a deux côtés égaux.

carre
Warning Peut-on toujours substituer un Carré à la place d’un Rectangle ?

Interface Segregation Principle

solid i
Préférer plusieurs interfaces spécifiques pour chaque client plutôt qu'une
seule interface générale

Dependency Inversion Principle

solid d
Il faut dépendre des abstractions, pas des implémentations

DIP : explications

Ce principe indique :

  • Les modules de haut niveau (abstraits) ne doivent pas dépendre des modules de bas niveau. Les deux doivent dépendre d’abstractions.
  • Les abstractions ne doivent pas dépendre des détails d’implémentation. C’est l’inverse : les détails doivent dépendre des abstractions.
Note Ainsi ce principe va à l’encontre de l’intuition classique.

SOLID et patrons

Important
QUESTION

Lesquels des 5 principes SOLID s’appliquent bien à Strategy ?

SOLID et patrons (éléments de réponses)

Quelques éléments de réponses :

Single Responsibility Principle

Bof

Open-Closed Principle

Oui : extension (du comportement) sans toucher au code!

Liskov Substitution Principle

Non

Interface Segregation Principle

Oui, mais pas spécifiquement

Dependency Inversion Principle

Oui : les algos dépendent des mêmes abstractions que les données (les interfaces)

GRASP

The critical design tool for software development is a mind well educated in design principles. It is not the UML or any other technology.

Craig Larman, 2005

Il s’agit d’un ensemble de patrons, plutôt orientés conception (UML). Nous en aborderons certains au travers des exemples de ce module (cf. [Larman05]).

Les patrons : comment ça marche ?

Intérêt

  • Réponses éprouvées à des problèmes récurrents
  • Vocabulaire commun

T’as qu’à utiliser une factory!

Warning
QUESTION

Qui fait la nuit de l’info dans un groupe avec des Masters?

Définifion

  • Nom
  • Problème
  • Solution
  • Conséquences

Exemple de Strategy :

Nom

Strategy

Problème

Situations où il est nécessaire de permuter dynamiquement les algorithmes utilisés

Solution

Définir une famille d’algorithmes, encapsuler chacun d’eux en tant qu’objet, et les rendre interchangeables.

Conséquences

Ce patron laisse les algorithmes changer indépendamment des clients qui les emploient.

Patrons à aborder

Patrons à aborder

  • Les "pressentis"

Patrons à aborder

  • Les nouveaux

    • Décorateur
    • Commande
    • Adaptateur
    • Façade
    • Patron de méthode

Patrons à aborder

  • Les "avancés"

    • Chaînes de responsabilité
    • Visiteur

Patrons à aborder

  • Ceux qu’on n’aura pas le temps d’aborder

    • Prototype
    • Mémento
    • Médiateur
    • Interprète
    • Poids-mouche
    • Monteur
    • Pont

Patrons à aborder

  • Concepts avancés

    • Patrons de patrons (exemple du MVC)
    • Anti-patrons

Time for a quizz!

Warning
QUESTION
  • Connectez-vous sur : http://www.socrative.com/ (student login)
  • Ou téléchargez l’application pour étudiant socrative2
  • Choisissez la room 44918d67

Quizz

quizz1

Quizz

quizz2

Quizz

quizz3

Quizz

quizz4

Quizz

quizz5

Quizz

quizz6

Quizz

quizz7

Quizz

quizz8

Quizz

quizz9

Quizz

quizz10

Quizz

quizz11

Quizz

quizz12

Quizz

quizz13

Glossaire et définition

Warning Ces définitions seront enrichies au fur et à mesure des patrons étudiés.

Patrons de création

Singleton

Singleton garantit qu’une classe n’a qu’une seule instance et fournit un point d’accès global à cette instance.

singleton

Patrons comportementaux

Observateur (Observeruk)

Observateur définit une relation entre objets de type un-à-plusieurs, de façon que, lorsqu’un objet change d’état, tous ceux qui en dépendent en soient notifiés et soient mis à jour automatiquement.

Stratégie (Strategyuk)

Stratégie définit une famille d’algorithmes, encapsule chacun d’eux et les rend interchangeables. Il permet à l’algorithme de varier indépendamment des clients qui l’utilisent.

strategy

Références

  • [GoF] Design Patterns: Elements of reusable object oriented software. 1994.
  • [Freeman04] Design Pattren - Head First, O’Reilly, 09/2004.
  • [Cysboy] Apprenez à programmer en Java. Par cysboy. Disponible ici (le 2014-11-18).
  • GOPROD - De bonnes pratiques au service de la conception orientée objets. Disponible ici (le 2014-11-18).
  • [Larman05] Larman, Craig. Applying UML and Patterns – An Introduction to Object-Oriented Analysis and Design and Iterative Development (3rd ed.). Prentice Hall. 2005. ISBN 0-13-148906-2.
  • [Meyer88] Meyer, Bertrand. Object-Oriented Software Construction. Prentice Hall. 1988. ISBN 0-13-629049-3.
  • [Martin03] “Principles Of OOD”, Robert C. Martin (“Uncle BOB”), http://butunclebob.com (Last verified 2014-07-17). Note the reference to “the first five principles”, though the acronym is not used in this article. Dates back to at least 2003.

Conventions d’écriture

Diagrammes UML

Les diagrammes UML™ sont réalisés avec plantUML avec des conventions graphiques propres qui sont listées ci-dessous.

conventions1
Figure 1. Convention http://plantuml.sourceforge.net/[plantUML] pour la visibilité des propriétés/méthodes
conventions
Figure 2. Symboles pour les types de classes

Crédits photos

About…​

Document réalisé par Jean-Michel Bruel via Asciidoctor (version 1.5.1) de 'Dan Allen', lui même basé sur AsciiDoc. Pour l’instant ce document est libre d’utilisation et géré par la 'Licence Creative Commons'. Licence Creative Commons licence Creative Commons Paternité - Partage à l'Identique 3.0 non transposé.

/